#include<iostream>
#include<sys/types.h>
#include<sys/socket.h>
#include<cerrno>
#include<string>
#include<cstring>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<signal.h>



void Usage(std::string proc)
{
  std::cout<<"Usage: "<<proc<<" port"<<std::endl;
}

void ServerIO(int new_sock)
{
  while(true)
  {
    char buffer[1024];
    memset(buffer,0,sizeof(buffer));
    ssize_t s = read(new_sock,buffer,sizeof(buffer)-1);
    if(s>0)//读取成功
    {
      buffer[s]=0;
      std::cout<<"client# "<<buffer<<std::endl;
      std::string echo_string = ">>>server<<<, ";
      echo_string+=buffer;

      write(new_sock,echo_string.c_str(),echo_string.size());
    }
    else if(s==0)
    {
      std::cout<<"client quit..."<<std::endl;
      break;
    }
    else{
      std::cout<<"read err"<<std::endl;
      break;
    }
  }
}

// ./tcp_server port
int main(int argc,char* argv[])
{
  if(argc!=2)
  {
    Usage(argv[0]);
    return 1;
  }

  //tcp_server
  //1.创建套接字，此套接字为监听套接字，用于绑定和监听
  int Listen_sock = socket(AF_INET,SOCK_STREAM,0);//AF_INET为协议域，表示是IPV4，SOCK_STREAM为协议类型，表示TCP协议
  //tcp是流式的，与文件强相关，因此与文件操作接口一起使用
  //2.bind绑定IP和端口号
  //填充结构体
  struct sockaddr_in local;
  memset(&local,0,sizeof(local));
  local.sin_family = AF_INET;
  local.sin_port = htons(atoi(argv[1]));
  local.sin_addr.s_addr = INADDR_ANY;

  bind(Listen_sock,(struct sockaddr*)&local,sizeof(local));

  //将服务器设置为监听状态
  const int back_log = 5;
  listen(Listen_sock,back_log);

  //监听状态后的服务器，可以accept客户端了
  
  signal(SIGCHLD,SIG_IGN);

  for(;;)
  {
    struct sockaddr_in peer;
    socklen_t len = sizeof(peer);
    int acc_sock = accept(Listen_sock,(struct sockaddr*)&peer,&len);

    std::cout<<"get a new link..."<<acc_sock<<std::endl;

    ServerIO(acc_sock);

  }
  close(acc_sock);
  

  return 0;
}
